#ifndef __cache_ctrl_h__
#define __cache_ctrl_h__
#pragma once

#include "cache.cpp"

#define N_L1_CACHELINES_IN_BITS 9
#define N_L1_WAYS_IN_BITS 2
#define N_L1_LEN_IN_BITS  5

#define N_L2_CACHELINES_IN_BITS 9
#define N_L2_WAYS_IN_BITS 4
#define N_L2_LEN_IN_BITS  5
#define N_WR_BUFF 4

class CCacheCtrl
{
	CCache<N_L1_CACHELINES_IN_BITS,N_L1_WAYS_IN_BITS,N_L1_LEN_IN_BITS,char> L1_D_Cache;
	CCache<N_L1_CACHELINES_IN_BITS,N_L1_WAYS_IN_BITS,N_L1_LEN_IN_BITS,char> L1_I_Cache;
	CCache<N_L2_CACHELINES_IN_BITS,N_L2_WAYS_IN_BITS,N_L2_LEN_IN_BITS,char> L2_Cache;

	struct tag_wr_buffer
	{
	
		__u32 address;
		__u8 data[32];
		 
	} write_buffer[N_WR_BUFF];

	int stack_top;

	char index_stack[N_WR_BUFF];

	bool cache_enabled;

public:
	CCacheCtrl ():cache_enabled(false),stack_top(0)
	{}


	bool enabled() {return cache_enabled;}

	__u8 read_byte (__u32 address);
	__u16 read_short(__u32 address);
	__u32 read_int(__u32 address);

	void write_byte (__u32 address,__u8  dat);
	void write_short(__u32 address,__u16 dat);
	void write_int(__u32 address,__u32 dat);

	__u32 icache_read_int(__u32 address);

	void write_l2_line(__u32 address,__u8 * data);
	void write_l1_line(__u32 address,__u8 * data);

private:
	int get_wr_buf_no();
	void read_line(__u32 address,__u8 * p_data);
	void pushto_wr_buffer(__u32 address,__u8 * p_data);
};

#endif //__cache_ctrl_h__